/*
 * claplanparser.h
 *
 *  Created on: 30 Oct 2013
 *      Author: Tom Vercauteren
 */

#ifndef CLAPLANPARSER_H_
#define CLAPLANPARSER_H_

#include <string>
#include <iostream>
#include <fstream>

#include "claplan_header.h"
#include "claplan_optimization.h"
#include "claplan_target.h"
#include "claplan_data.h"
#include "claplan_beam.h"

/** Defines the different sections within a claplan */
enum ClaplanSections
{
	/** defines the header */
	HEADER,
	/** defines the general optimization parameters */
	OPTIMIZATION,
	/** defines the fractionation scheme */
	FRACTIONATION,
	/** defines target objectives and contraints */
	TARGET,
	/** defines OAR contraints */
	OAR,
	/** defines the beam parameters */
	BEAM,
	/** defines parameter based on the key value concept */
	KEY_VALUE,
	/** defines an empty line */
	EMTPY
};

// forward declarations
class Parser;
class HeaderParser;
class FractionationParser;
class ClaplanParser;
class TargetParser;
class OarParser;
class BeamParser;

/**
 * A parser interface class for processing claplan files.
 */
class Parser
{
public:
	Parser()
	{
	}
	virtual ~Parser()
	{
	}
	/**
	 * Parse one line of text based on keywords.
	 * @param line line to be parsed
	 * @return
	 * <ul>
	 *      <li> >=1: number of keywords parsed </li>
	 *      <li>   0: no keywords were found in the line that could be parsed</li>
	 *      <li>  -1: an error occurred while parsing the line</li>
	 * </ul>
	 */
	virtual int parse(const std::string &line) = 0;
	/**
	 * Parse an input stream of text based on keywords.
	 * @param input an input stream
	 * @return
	 * <ul>
	 *      <li> >=1: number of keywords parsed </li>
	 *      <li>   0: no keywords were found in the line that could be parsed</li>
	 *      <li>  -1: an error occurred while parsing the line</li>
	 * </ul>
	 */
	virtual int parse(std::istream &input) = 0;

	/**
	 * Check if a string is a comment.
	 * A comment is defined as a string that starts with : #
	 * @param line line to be checked
	 * @return
	 * <ul>
	 * 	<li>true : line is comment</li>
	 * 	<li>false : line is not comment</li>
	 * </ul>
	 */
	bool isComment(const std::string &line);
	/**
	 * Check if a string is a section starter.
	 * Sections are defined by the enum : ClaplanSections
	 * @param line line to be checked
	 * @return
	 * <ul>
	 * 	<li>true : line is section starter</li>
	 * 	<li>false : line is not section starter</li>
	 * </ul>
	 */
	bool isSection(const std::string &line);
};

/**
 * Parser to parse the claplan header section.
 */
class HeaderParser: public Parser
{
public:
	/** Header parameters */
	ClaplanHeader *header;

	HeaderParser() :
			header(0)
	{
	}

	virtual ~HeaderParser()
	{
		header = 0;
	}
	virtual int parse(const std::string &line);
	virtual int parse(std::istream &input);
};

/**
 * A parser that can parser the optimization section within the claplan.
 */
class OptimizationParser: public Parser
{
public:
	/** Optimization parameters */
	ClaplanOptimization *op;

	OptimizationParser() :
			op(0)
	{
	}

	virtual ~OptimizationParser()
	{
		op = 0;
	}
	virtual int parse(const std::string &line);
	virtual int parse(std::istream &input);
};

/**
 * Parser to parse the claplan fractionation section.
 */
class FractionationParser: public Parser
{
public:
	/** FractionationParser parameters */
	ClaplanData *data;
private:

public:
	FractionationParser() :
			data(0)
	{
	}

	virtual ~FractionationParser()
	{
		data = 0;
	}
	virtual int parse(const std::string &line);
	virtual int parse(std::istream &input);
};

/**
 * Parser to parse the claplan target section.
 */
class TargetParser: public Parser
{
public:
	/** data pointer */
	ClaplanData *data;
private:
	/** current claplan target pointer */
	ClaplanTarget *ct;

public:
	TargetParser() :
			data(0), ct(0)
	{
	}

	virtual ~TargetParser()
	{
		data = 0;
		ct = 0;
	}
	virtual int parse(const std::string &line);
	virtual int parse(std::istream &input);
};

/**
 * Parser to parse the claplan oar section.
 */
class OarParser: public Parser
{
public:
	/** data pointer */
	ClaplanData *data;
private:
	/** current claplan oar pointer */
	ClaplanOar *co;

public:
	OarParser() :
			data(0), co(0)
	{
	}

	virtual ~OarParser()
	{
		data = 0;
		co = 0;
	}
	virtual int parse(const std::string &line);
	virtual int parse(std::istream &input);
};

/**
 * Parser to parse the claplan beam section.
 */
class BeamParser: public Parser
{
public:
	/** data pointer */
	ClaplanData *data;
private:
	/** current claplan oar pointer */
	ClaplanBeam *cb;

public:
	BeamParser() :
			data(0), cb(0)
	{
	}

	virtual ~BeamParser()
	{
		data = 0;
		cb = 0;
	}
	virtual int parse(const std::string &line);
	virtual int parse(std::istream &input);
};

class ClaplanParser: public Parser
{
private:
	Parser *parser;
	ClaplanData *data;
	HeaderParser *headerParser;
	OptimizationParser *optParser;
	FractionationParser *fracParser;
	TargetParser *targetParser;
	OarParser *oarParser;
	BeamParser *beamParser;

public:
	/**
	 * Constructor creates the different parsers and sets the data pointers to 0.
	 */
	ClaplanParser() :
			parser(0), data(0)
	{
		headerParser = new HeaderParser();
		optParser = new OptimizationParser();
		fracParser = new FractionationParser();
		targetParser = new TargetParser();
		oarParser = new OarParser();
		beamParser = new BeamParser();
	}
	/**
	 * The destructor destroys the different parsers within the parser but only
	 * unlinks the data pointers because the might be needed elsewhere after
	 * the parser is destroyed.
	 */
	virtual ~ClaplanParser()
	{
		data = 0;
		delete headerParser;
		headerParser = 0;
		delete optParser;
		optParser = 0;
		delete fracParser;
		fracParser = 0;
		delete targetParser;
		targetParser = 0;
		delete oarParser;
		oarParser = 0;
		delete beamParser;
		beamParser = 0;
	}
	virtual int parse(const std::string &line);
	virtual int parse(std::istream &input);

	/**
	 * Set the claplan data
	 * @param data Claplan data
	 */
	void setClaplanData(ClaplanData *data)
	{
		this->data = data;
	}
	/**
	 * Get a pointer to the claplan data.
	 * @return Pointer to the claplan data.
	 */
	ClaplanData* getClaplanData() const
	{
		return data;
	}

};

#endif /* CLAPLANPARSER_H_ */
